"""
:param 打卡数据绘图接口
:return 图表对象
"""
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Map3D, Funnel, Line, Pie
from pyecharts.globals import ChartType
from pyecharts.commons.utils import JsCode
from studata import StuData

stu_info = StuData()  # 数据对象
stu_info.load_data()  # 加载数据


class StuCharts:
    def __init__(self):
        self.province = []  # 建立省份列表
        self.confirm = []  # 建立人数列表

    def Map3D_base(self):
        # Map3D图
        # 地理可视化
        china_data = {}
        for key in stu_info.location.keys():
            self.province.append(key)  # 获取数据中的省份
            self.confirm.append(stu_info.location[key])  # 获取对应省份的confirm
            china_data = pd.DataFrame({"province": self.province, "confirm": self.confirm})  # 把province和confirm两个列表合并
        # eg:a=['A','B','C'],b=[1,2,3]经过上边步骤后会变成c=[('A',1),('B',2),('C',3)]
        province_data = {  # 省份的地址信息
            '黑龙江省': [127.9688, 45.368, 0],
            '内蒙古自治区': [110.3467, 41.4899, 0],
            '吉林省': [125.8154, 44.2584, 0],
            '辽宁省': [123.1238, 42.1216, 0],
            '河北省': [114.4995, 38.1006, 0],
            '天津市': [117.4219, 39.4189, 0],
            '山西省': [112.3352, 37.9413, 0],
            '陕西省': [109.1162, 34.2004, 0],
            '甘肃省': [103.5901, 36.3043, 0],
            '宁夏回族自治区': [106.3586, 38.1775, 0],
            '青海省': [101.4038, 36.8207, 0],
            '新疆维吾尔族自治区': [87.9236, 43.5883, 0],
            '西藏自治区': [91.11, 29.97, 0],
            '四川省': [103.9526, 30.7617, 0],
            '重庆市': [108.384366, 30.439702, 0],
            '山东省': [117.1582, 36.8701, 0],
            '河南省': [113.4668, 34.6234, 0],
            '江苏省': [118.8062, 31.9208, 0],
            '安徽省': [117.29, 32.0581, 0],
            '湖北省': [114.3896, 30.6628, 0],
            '浙江省': [119.5313, 29.8773, 0],
            '福建省': [119.4543, 25.9222, 0],
            '江西省': [116.0046, 28.6633, 0],
            '湖南省': [113.0823, 28.2568, 0],
            '贵州省': [106.6992, 26.7682, 0],
            '广西壮族自治区': [108.479, 23.1152, 0],
            '海南省': [110.3893, 19.8516, 0],
            '上海市': [121.4648, 31.2891, 0],
            '广东省': [113.28064, 23.125177, 0],
            '北京市': [116.405289, 39.904987, 0],
            '云南省': [102.71225, 25.040609, 0],
            '香港': [114.165460, 22.275340, 0],
            '澳门': [113.549130, 22.198750, 0],
            '台湾': [121.5200760, 25.0307240, 0]
        }
        province = list(china_data['province'])
        for i in province_data.copy():
            if i not in province:
                del province_data[i]

        for item in [list(z) for z in zip(china_data["province"], china_data["confirm"])]:
            province_data[item[0]][-1] = item[1]
        Map_3D = (
            Map3D()
                .add_schema(
                pos_height="110%",
                pos_top="0",
                itemstyle_opts=opts.ItemStyleOpts(
                    color="rgb(5,101,123)",
                    opacity=1,
                    border_width=0.8,
                    border_color="rgb(62,215,213)",
                ),
                map3d_label=opts.Map3DLabelOpts(
                    is_show=False,
                    formatter=JsCode("function(data){return data.name + " " + data.value[2];}"),
                ),
                emphasis_label_opts=opts.LabelOpts(
                    is_show=False,
                    color="#fff",
                    font_size=10,
                    background_color="rgba(0,23,11,0)",
                ),
                light_opts=opts.Map3DLightOpts(
                    main_color="#fff",
                    main_intensity=1.2,
                    main_shadow_quality="high",
                    is_main_shadow=False,
                    main_beta=10,
                    ambient_intensity=0.3,
                ),
            )
                .add(
                series_name="省份",
                data_pair=list(zip(list(province_data.keys()), list(province_data.values()))),
                # 上步用于确定个省份的经纬度
                type_=ChartType.BAR3D,
                bar_size=1,
                shading="lambert",
                label_opts=opts.LabelOpts(
                    is_show=False,
                ),
            )
                .set_global_opts(
                title_opts=opts.TitleOpts(title="学生假期归属地可视化", pos_left='34%', pos_top='17%'),
                legend_opts=opts.LegendOpts(is_show=False)
            )
        )
        return Map_3D

    def line_base_of_staff(self):
        # line图
        # 学生打卡人数变化趋势
        y_data = list(stu_info.history_sign.values())  # 获取文件中每天的打卡人数作为y轴
        x_data = list(stu_info.history_sign.keys())  # 获取文件中每天的日期作为x轴

        Line_staff = (
            Line()
                .add_xaxis(xaxis_data=x_data)
                .add_yaxis(
                series_name="打卡人数",
                stack="总量",
                y_axis=y_data,
                is_symbol_show=False,
                is_smooth=True,
                linestyle_opts=opts.LineStyleOpts(width=3, opacity=0.5),
                label_opts=opts.LabelOpts(is_show=False),
                markline_opts=opts.MarkLineOpts(
                    data=[
                        opts.MarkLineItem(type_="average", name="平均值"),
                        opts.MarkLineItem(symbol="none", x="90%", y="max"),
                    ],
                    symbol_size=5,
                    linestyle_opts=opts.LineStyleOpts(color='#6F7DE1', opacity=0.8, type_='dashed')
                ),
            )
                .set_global_opts(
                tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
                legend_opts=opts.LegendOpts(is_show=False),
                title_opts=opts.TitleOpts(title="学生打卡总人数变化趋势", pos_left='30%', pos_top='7%'),
                yaxis_opts=opts.AxisOpts(
                    type_="value",
                    axistick_opts=opts.AxisTickOpts(is_show=True),
                ),
                xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
                datazoom_opts=[opts.DataZoomOpts(type_="inside", xaxis_index=0, is_zoom_lock=False, range_start=10,
                                                 range_end=100), ],
            )
        )
        return Line_staff

    def line_base_of_grades(self):
        # line图
        # 各年级打卡人数变化趋势，汇总在一张图，三条折线。

        Line_grades = (
            Line()
                .set_global_opts(
                title_opts=opts.TitleOpts(title="各年级打卡人数变化趋势", pos_left='33%', pos_top='7%'),
                tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
                legend_opts=opts.LegendOpts(is_show=False),
                xaxis_opts=opts.AxisOpts(type_="category"),
                yaxis_opts=opts.AxisOpts(
                    type_="value",
                    axistick_opts=opts.AxisTickOpts(is_show=True),
                ),
                datazoom_opts=[opts.DataZoomOpts(type_="inside", xaxis_index=0, is_zoom_lock=False, range_start=10,
                                                 range_end=100), ],
            )
                .add_xaxis(xaxis_data=list(stu_info.history_sign_of_2017.keys()))  # 从文件中获取2017级每天打卡的日期
                .add_yaxis(
                series_name="2017级",
                y_axis=list(stu_info.history_sign_of_2017.values()),  # 从文件中获取2017级每天打卡的人数
                is_symbol_show=False,
                is_smooth=True,
                linestyle_opts=opts.LineStyleOpts(width=3, opacity=0.5),
                label_opts=opts.LabelOpts(is_show=False),
            )
                .add_xaxis(xaxis_data=list(stu_info.history_sign_of_2018.keys()))
                .add_yaxis(
                series_name="2018级",
                y_axis=list(stu_info.history_sign_of_2018.values()),
                is_symbol_show=False,
                is_smooth=True,
                linestyle_opts=opts.LineStyleOpts(width=3, opacity=0.5, color='#8B6969'),
                label_opts=opts.LabelOpts(is_show=False),
            )
                .add_xaxis(xaxis_data=list(stu_info.history_sign_of_2019.keys()))
                .add_yaxis(
                series_name="2019级",
                y_axis=list(stu_info.history_sign_of_2019.values()),
                is_symbol_show=False,
                is_smooth=True,
                linestyle_opts=opts.LineStyleOpts(width=3, opacity=0.5, color='#EE6363'),
                label_opts=opts.LabelOpts(is_show=False),
            )
        )
        return Line_grades

    def Funnel_base_of_teacher(self):
        # Funnel图
        # 最近一日(8月31号)，教职工和三个年级打卡完成率（打卡人数/人数）制作的漏斗图。
        data = {}  # 记录教职工和三个年级打卡完成率
        data["2017级"] = round((stu_info.history_sign_of_2017['2020-8-31'] / 600), 4) * 100
        data["2018级"] = round((stu_info.history_sign_of_2018['2020-8-31'] / 600), 4) * 100
        data["2019级"] = round((stu_info.history_sign_of_2019['2020-8-31'] / 600), 4) * 100
        Funnel_teacher = (
            Funnel()
            .add(
                "完成率",
                [list(z) for z in zip(data.keys(), data.values())],
                sort_="ascending",
                label_opts=opts.LabelOpts(position="inside"),  # 指定标签的位置 和百分比 inside / outside
                tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b} : {c}%")
            )
            .set_global_opts(
                title_opts=opts.TitleOpts(title="各年级学生打卡完成率状况", pos_left='25%', pos_top='5%'),
                legend_opts=opts.LegendOpts(is_show=False)
            )
        )
        return Funnel_teacher

    def Pie_base_of_late_sign_in(self):
        # Pie图
        # 最近一日(8月31号)，20:00后打卡，年级组成分析
        data_list = [list(z) for z in zip(stu_info.sign_in_after_twenty.keys(), stu_info.sign_in_after_twenty.values())]
        Pie_sign = (
            Pie()
            .add(
                "",
                data_list,
                label_opts=opts.LabelOpts(position='inside')
            )
            .set_global_opts(
                title_opts=opts.TitleOpts(
                    title="学生未及时打卡状况(20点后)",
                    pos_top='0%',
                    pos_left='28%',
                ),
                legend_opts=opts.LegendOpts(is_show=False)
            )
            .set_series_opts(
                label_opts=opts.LabelOpts(formatter="{b}: {c}", position='inside'),
            )
        )
        return Pie_sign


if __name__ == '__main__':
    C = StuCharts()
    C.Map3D_base()
    C.Funnel_base_of_teacher()
    C.line_base_of_grades()
    C.line_base_of_staff()
    C.Pie_base_of_late_sign_in()
